package cinvestav.adviseme.databasemodel;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import cinvestav.adviseme.datamodel.Foto;
import cinvestav.adviseme.datamodel.Lugar;
import cinvestav.adviseme.datamodel.Persona;
import cinvestav.adviseme.datamodel.TipoLugar;
import cinvestav.adviseme.util.DBException;
import cinvestav.adviseme.util.DataBaseDictionary;

public class FotoDB extends DataBase implements IFotoDB {
	
	private static Logger log = Logger.getLogger(FotoDB.class.getName());
	public FotoDB() throws DBException {
		super();
	}

	public List<Foto> getByFilters(Map<String, String[]> filtros)
			throws DBException {
		Connection c = this.getConnection();
		try {

			// Establece la conexion
			
			// Prepara cadena a ejecutar
			PreparedStatement ps = genPreparedStatementeString(filtros, c);
			log.log(Level.INFO,"SQL = ",ps.toString());
			// Ejecuta consulta
			ResultSet res = this.ejecutarQuery(ps);

			List<Foto> fotos = new LinkedList<Foto>();

			while (res.next()) {
				Foto foto = new Foto();
				Persona persona = new Persona();				
				Lugar lugar = new Lugar();
				TipoLugar tipoLugar = new TipoLugar();
				
				foto.setId(res.getInt("ide_fot"));
				foto.setUrl(res.getString("url_fot"));
				
				persona.setId(res.getInt("ide_per"));
				persona.setNombrePersona(res.getString("nom_per"));
				persona.setApellidoPaterno(res.getString("app_per"));
				persona.setApellidoMaterno(res.getString("apm_per"));
				persona.setFotografia(res.getString("fot_per"));
				
				lugar.setId(res.getInt("ide_lug"));
				lugar.setNombre(res.getString("nom_lug"));
				lugar.setDescripcion(res.getString("des_lug"));
				lugar.setRanking(res.getInt("ran_lug"));
				
				tipoLugar.setId(res.getInt("ide_tip"));
				tipoLugar.setDescripcion(res.getString("des_tip"));
				lugar.setTipo(tipoLugar);
				
				foto.setPersona(persona);
				foto.setLugar(lugar);
				fotos.add(foto);
				log.log(Level.INFO,"ADD FOTO="+foto);
			}
			c.close();
			return fotos;
		} catch (SQLException e) {
			// TODO: handle exception
			log.log(Level.SEVERE,
					null, e);
			throw new DBException("Error al ejecutar la consulta:\n"
					+ e.getMessage());
		} catch (DBException e) {
			throw new DBException(e);
		}		
	}

	private PreparedStatement genPreparedStatementeString(
			Map<String, String[]> filtros, Connection c) {
		String statement = DataBaseDictionary.GET_BASE_FOTOS;
		String alias = DataBaseDictionary.ALIAS_FOTO;

		Boolean ini = Boolean.TRUE;

		for (Map.Entry<String, String[]> entry : filtros.entrySet()) {
			if (ini) {
				statement += " " + alias + "." + entry.getKey();
				ini = Boolean.FALSE;
			} else {
				statement += " AND " + alias + "." + entry.getKey();
			}
		}
		log.log(Level.INFO,"SLQ = "+statement);
		try {
			PreparedStatement ps = c.prepareStatement(statement);
			int cont = 1;

			for (Map.Entry<String, String[]> entry : filtros.entrySet()) {
				String[] val = entry.getValue();
				if (val[1].compareTo(DataBaseDictionary.STRING_SIMPLE) == 0) {
					ps.setString(cont, val[0]);
				} else if (val[1].compareTo(DataBaseDictionary.STRING_JOKER) == 0) {
					ps.setString(cont, val[0] + "%");
				} else if (val[1]
						.compareTo(DataBaseDictionary.STRING_DOBLE_JOKER) == 0) {
					ps.setString(cont, "%" + val[0] + "%");
				} else if (val[1].compareTo(DataBaseDictionary.INTEGER_TYPE) == 0) {
					// Cuando el valor es entero
					ps.setInt(cont, Integer.parseInt(val[0]));
				}
				cont++;
			}
			return ps;
		} catch (SQLException ex) {
			// TODO: handle exception
			log.log(Level.SEVERE, null, ex);
		}
		return null;
	}

	@Override
	public Foto insert(Foto foto) throws DBException {
		// TODO Auto-generated method stub
		try{
			// Establece la conexion
			Connection c = this.getConnection();
			Integer idFoto = 0;

			// Si no, se procede a insertar el lugar Agregado
			PreparedStatement ps = c
					.prepareStatement(DataBaseDictionary.INSERT_FOTO);
			/*
			 * Se insertan los parametros al insert 
			 * [1] = URL de la fotografia
			 * [2] = ID de la persona que lo agrega 
			 * [3] = ID del lugar de la foto
			 */

			ps.setString(1, foto.getUrl());
			ps.setInt(2, foto.getPersona().getId());
			ps.setInt(3, foto.getLugar().getId());

			// Se realiza la consulta
			this.ejecutarInstruccion(ps);

			//Actualizar tabla Lugar
			ps = c.prepareStatement(DataBaseDictionary.UPDATE_LUGAR_FOTO_URL);
			/**
			 * Parametros PS
			 * [1] = URL de la foto 
			 * [2] = ide del lugar
			 */
			ps.setString(1, foto.getUrl());
			ps.setInt(2, foto.getLugar().getId());
			
			// Se realiza la consulta
			this.ejecutarInstruccion(ps);
			
			// Se obtiene el ID de la ultima foto insertada en la base
			ps = c.prepareStatement(DataBaseDictionary.GET_LAST_FOTO);
			ResultSet res = this.ejecutarQuery(ps);
			while (res.next()) {
				idFoto = res.getInt("ide_fot");
			}

			log.log(Level.INFO, "ID FOTO INS = " + idFoto);
			
			if (idFoto != 0) {
				foto.setId(idFoto);
			} else {
				throw new DBException("ERROR AL INSERTAR");
			}

			c.close();
			return foto;

		} catch (SQLException ex) {
			log.log(Level.SEVERE, null, ex);
			throw new DBException("Error al ejecutar la consulta:\n"
					+ ex.getMessage(), ex);
		}
	}

}
